﻿using UtilZ.Dotnet.Ex.Communication.Base;
using UtilZ.Dotnet.Ex.Model;

namespace UtilZ.Dotnet.Ex.Communication.Net.Tcp
{
    /// <summary>
    /// TCP分包器-收到一个包就直接输出
    /// </summary>
    public class NetTCPUnpacker : UnpackerAbs
    {
        /// <summary>
        /// 分包器使用模式
        /// </summary>
        private readonly UnpackerUseMode _useMode;

        private readonly DataOutputArgs _args = null;
        private DataSource _bufferData = null;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="useMode">分包器使用模式</param>
        public NetTCPUnpacker(UnpackerUseMode useMode = UnpackerUseMode.Monopolize)
        {
            this._useMode = useMode;

            if (useMode == UnpackerUseMode.Monopolize)
            {
                this._args = new DataOutputArgs();
            }
        }


        /// <summary>
        /// 对数据进行拆包
        /// </summary>
        /// <param name="unpackerPara">分包参数</param>
        /// <returns>拆包成功的数据长度</returns>
        protected override int PrimitiveUnPackge(IUnpackerPara unpackerPara)
        {
            var para = (NetTcpUnpackerPara)unpackerPara;
            if (para.DataLength <= 0)
            {
                return para.DataLength;
            }

            if (this._useMode == UnpackerUseMode.Monopolize)
            {
                if (this._bufferData == null || this._bufferData.Bytes != para.Buffer)
                {
                    this._bufferData = new DataSource(para.Buffer, para.Offset, para.DataLength);
                }
                else
                {
                    this._bufferData.Update(para.Offset, para.DataLength);
                }

                this._args.Update(para.LinkInfo, this._bufferData);
                base.OnRaiseOnReceivedData(para.Client, this._args);
            }
            else
            {
                var args = new DataOutputArgs(unpackerPara.LinkInfo, new DataSource(para.Buffer, para.Offset, para.DataLength));
                base.OnRaiseOnReceivedData(para.Client, args);
            }

            return para.DataLength;
        }

    }
}
